/*-
 * Copyright (c) 2013 Shang-Rong Cai. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $ MTBLAS TEST: tst_lv_a_com.c    Rev. 0.0.10    2013-11-11T12:31+08:00 $
 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <complex.h>
#include <time.h>

#include <tst_lv_a_com.h>

float rand_coef_ff()
{
    float value;

    switch (random() % ZERO_FREQUENCY)
    {
        case 0:
            value = 0;
            break;
        case 1:
            value = 1.0;
            break;
        default:
            value = random_float();
            break;
    }

    return value;
}


double rand_coef_df()
{
    double value;

    switch (random() % ZERO_FREQUENCY)
    {
        case 0:
            value = 0;
            break;
        case 1:
            value = 1.0;
            break;
        default:
            value = random_double();
            break;
    }

    return value;
}


long double rand_coef_lf()
{
    long double value;

    switch (random() % ZERO_FREQUENCY)
    {
        case 0:
            value = 0;
            break;
        case 1:
            value = 1.0;
            break;
        default:
            value = random_long_double();
            break;
    }

    return value;
}


float complex rand_coef_fc()
{
    float complex value;

    switch (random() % ZERO_FREQUENCY)
    {
        case 0:
            value = 0;
            break;
        case 1:
            value = 1.0;
            break;
        default:
            value = random_float() + _Complex_I * random_float();
            break;
    }

    return value;
}


double complex rand_coef_dc()
{
    double complex value;

    switch (random() % ZERO_FREQUENCY)
    {
        case 0:
            value = 0;
            break;
        case 1:
            value = 1.0;
            break;
        default:
            value = random_double() + _Complex_I * random_double();
            break;
    }

    return value;
}


long double complex rand_coef_lc()
{
    long double complex value;

    switch (random() % ZERO_FREQUENCY)
    {
        case 0:
            value = 0;
            break;
        case 1:
            value = 1.0;
            break;
        default:
            value = random_long_double() + _Complex_I * random_long_double();
            break;
    }

    return value;
}


void check_value_ff_stdout(char *msg, float val)
{
    unsigned char lst[4];

    memcpy((void*) lst, (void*) &val, 4);

    printf("%s% .6E\n", msg, val);
#ifndef NOHEX_DATA
    printf("    %02X%02X%02X%02X\n", lst[3], lst[2], lst[1], lst[0]);
#endif
}


void check_value_df_stdout(char *msg, double val)
{
    unsigned char lst[8];

    memcpy((void*) lst, (void*) &val, 8);

    printf("%s% .15lE\n", msg, val);
#ifndef NOHEX_DATA
    printf("    %02X%02X%02X%02X", lst[7], lst[6], lst[5], lst[4]);
    printf("  %02X%02X%02X%02X\n", lst[3], lst[2], lst[1], lst[0]);
#endif
}


void check_value_lf_stdout(char *msg, long double val)
{
    unsigned char lst[16];

    memcpy((void*) lst, (void*) &val, 16);

    printf("%s% .24LE\n", msg, val);
#ifndef NOHEX_DATA
    printf("    %02X%02X%02X%02X", lst[15], lst[14], lst[13], lst[12]);
    printf("  %02X%02X%02X%02X", lst[11], lst[10], lst[9], lst[8]);
    printf("  %02X%02X%02X%02X", lst[7], lst[6], lst[5], lst[4]);
    printf("  %02X%02X%02X%02X\n", lst[3], lst[2], lst[1], lst[0]);
#endif
}


void check_value_fc_stdout(char *msg, float complex val)
{
    unsigned char rlst[4];
    unsigned char ilst[4];

    float val_r, val_i;

    val_r = crealf(val);
    val_i = cimagf(val);

    memcpy((void*) rlst, (void*) &val_r, 4);
    memcpy((void*) ilst, (void*) &val_i, 4);

    printf("%s% .6E + % .6E i\n", msg, crealf(val), cimagf(val));
#ifndef NOHEX_DATA
    printf("    %02X%02X%02X%02X\n", rlst[3], rlst[2], rlst[1], rlst[0]);
    printf("    %02X%02X%02X%02X\n", ilst[3], ilst[2], ilst[1], ilst[0]);
#endif
}


void check_value_dc_stdout(char *msg, double complex val)
{
    unsigned char rlst[8];
    unsigned char ilst[8];

    double val_r, val_i;

    val_r = creal(val);
    val_i = cimag(val);

    memcpy((void*) rlst, (void*) &val_r, 8);
    memcpy((void*) ilst, (void*) &val_i, 8);

    printf("%s% .15E + % .15E i\n", msg, crealf(val), cimagf(val));
#ifndef NOHEX_DATA
    printf("    %02X%02X%02X%02X", rlst[7], rlst[6], rlst[5], rlst[4]);
    printf("  %02X%02X%02X%02X\n", rlst[3], rlst[2], rlst[1], rlst[0]);
    printf("    %02X%02X%02X%02X", ilst[7], ilst[6], ilst[5], ilst[4]);
    printf("  %02X%02X%02X%02X\n", ilst[3], ilst[2], ilst[1], ilst[0]);
#endif
}


void check_value_lc_stdout(char *msg, long double complex val)
{
    unsigned char rlst[16];
    unsigned char ilst[16];

    long double val_r, val_i;

    val_r = creall(val);
    val_i = cimagl(val);

    memcpy((void*) rlst, (void*) &val_r, 16);
    memcpy((void*) ilst, (void*) &val_i, 16);

    printf("%s% .24E + % .24E i\n", msg, crealf(val), cimagf(val));
#ifndef NOHEX_DATA
    printf("    %02X%02X%02X%02X", rlst[15], rlst[14], rlst[13], rlst[12]);
    printf("  %02X%02X%02X%02X", rlst[11], rlst[10], rlst[9], rlst[8]);
    printf("  %02X%02X%02X%02X", rlst[7], rlst[6], rlst[5], rlst[4]);
    printf("  %02X%02X%02X%02X\n", rlst[3], rlst[2], rlst[1], rlst[0]);
    printf("    %02X%02X%02X%02X", ilst[15], ilst[14], ilst[13], ilst[12]);
    printf("  %02X%02X%02X%02X", ilst[11], ilst[10], ilst[9], ilst[8]);
    printf("  %02X%02X%02X%02X", ilst[7], ilst[6], ilst[5], ilst[4]);
    printf("  %02X%02X%02X%02X\n", ilst[3], ilst[2], ilst[1], ilst[0]);
#endif
}


void mat_ff_stdout(mat_ff_t *ma)
{
    size_t zi;

    printf("Row Size: %zd, Column Size: %zd\n", ma->row_size, ma->col_size);

    for (zi = 0; zi < ma->size; zi++)
    {
        printf("[%10zd] % .6E\n", zi, ma->data[zi]);
    }
}


void mat_df_stdout(mat_df_t *ma)
{
    size_t zi;

    printf("Row Size: %zd, Column Size: %zd\n", ma->row_size, ma->col_size);

    for (zi = 0; zi < ma->size; zi++)
    {
        printf("[%10zd] % .15lE\n", zi, ma->data[zi]);
    }
}


void mat_lf_stdout(mat_lf_t *ma)
{
    size_t zi;

    printf("Row Size: %zd, Column Size: %zd\n", ma->row_size, ma->col_size);

    for (zi = 0; zi < ma->size; zi++)
    {
        printf("[%10zd] % .24LE\n", zi, ma->data[zi]);
    }
}


void mat_fc_stdout(mat_fc_t *ma)
{
    size_t zi;

    printf("Row Size: %zd, Column Size: %zd\n", ma->row_size, ma->col_size);

    for (zi = 0; zi < ma->size; zi++)
    {
        printf("[%10zd] % .6E + % .6E i\n", zi, crealf(ma->data[zi]), cimagf(ma->data[zi]));
    }
}


void mat_dc_stdout(mat_dc_t *ma)
{
    size_t zi;

    printf("Row Size: %zd, Column Size: %zd\n", ma->row_size, ma->col_size);

    for (zi = 0; zi < ma->size; zi++)
    {
        printf("[%10zd] % .15lE + % .15lE i\n", zi, creal(ma->data[zi]), cimag(ma->data[zi]));
    }
}


void mat_lc_stdout(mat_lc_t *ma)
{
    size_t zi;

    printf("Row Size: %zd, Column Size: %zd\n", ma->row_size, ma->col_size);

    for (zi = 0; zi < ma->size; zi++)
    {
        printf("[%10zd] % .24LE + % .24LE i\n", zi, creall(ma->data[zi]), cimagl(ma->data[zi]));
    }
}


double clock_difftime(struct timespec *tp_b, struct timespec *tp_e)
{
    double tt;

    tt = difftime(tp_e->tv_sec, tp_b->tv_sec);
    tt += (double) (tp_e->tv_nsec - tp_b->tv_nsec) / (double) 1000000000;

    return tt;
}
